<template>
    <tnxel-submit-form :model="model" inline>
        <div class="flex-v-center">
            <el-form-item label="简单枚举类型" prop="simple">
                <tnxel-enum-select v-model="model.simple" type="Boolean" selector="radio"/>
            </el-form-item>
            <el-form-item label=" " class="flex-1 me-0">
                <div class="w-100 flex-v-center justify-content-end">
                    <tnxel-button type="primary"
                        icon="fa-regular fa-floppy-disk"
                        :loading="saving"
                        @click="toSave"
                    >
                        保存 (Ctrl+S)
                    </tnxel-button>
                    <tnxel-button
                        type="default"
                        class="ms-2"
                        icon="bi bi-code-slash"
                        :key="clazz.modified"
                        :disabled="clazz.modified"
                        disabled-tip="已改动，需保存后才可生成代码"
                        @click="toGenerateCode"
                    >
                        生成代码
                    </tnxel-button>
                </div>
            </el-form-item>
        </div>
        <el-form-item label="常量集" class="mb-1" label-width="58px"></el-form-item>
        <tnxel-edit-table ref="constantTable"
            :data="model.constants"
            add-text="添加常量"
            :new-row="newConstant"
            :rules="constantRules"
            sortable>
            <el-table-column label="序号" type="index" align="center" width="60"/>
            <el-table-column label="定义名称" prop="name" align="center" width="150px">
                <template #default="{ row }">
                    <el-input v-model="row.name"/>
                </template>
            </el-table-column>
            <el-table-column label="显示名称" prop="caption" align="center" width="150px">
                <template #default="{ row }">
                    <el-input v-model="row.caption"/>
                </template>
            </el-table-column>
            <el-table-column label="持久化值" prop="value" align="center" width="150px">
                <template #default="{ row }">
                    <el-input v-model="row.value"/>
                </template>
            </el-table-column>
            <el-table-column label="适用场景" prop="scenes">
                <template #default="{ row }">
                    <tnxel-select class="mx-2" v-model="row.scenes" :items="sceneItems" selector="checkbox"/>
                </template>
            </el-table-column>
            <el-table-column label="克隆" align="center" width="60">
                <template #default="{ row }">
                    <tnxel-button type="primary" link icon="CopyDocument" @click="cloneConstant(row)"/>
                </template>
            </el-table-column>
        </tnxel-edit-table>
        <el-form-item label="场景定义" class="mb-1 mt-3" label-width="72px">
            <el-switch v-model="sceneEnabled" :disabled="model.subCaptions.length > 0"/>
        </el-form-item>
        <tnxel-edit-table ref="sceneTable"
            :data="model.subCaptions"
            add-text="添加场景"
            :new-row="newSubCaption"
            :rules="sceneRules"
            sortable
            v-if="sceneEnabled">
            <el-table-column label="序号" type="index" align="center" width="60"/>
            <el-table-column label="定义名称" prop="subname" align="center" width="150px">
                <template #default="{ row }">
                    <el-input v-model="row.subname"/>
                </template>
            </el-table-column>
            <el-table-column label="显示名称" prop="caption" align="center" width="150px">
                <template #default="{ row }">
                    <el-input v-model="row.caption"/>
                </template>
            </el-table-column>
            <el-table-column label="包含常量">
                <template #default="{ row }">
                    <div class="scene-constant-container">
                        <el-tag v-for="item of constantItems(row)" :key="item.name">
                            {{ item.name }} ({{ item.caption }})
                        </el-tag>
                    </div>
                </template>
            </el-table-column>
        </tnxel-edit-table>
    </tnxel-submit-form>
</template>

<script>
import tnx from '@/tnx';
import EnumClass from '@/logic/modeling/entity/EnumClass.js';
import EnumConstant from '@/logic/modeling/entity/EnumConstant.js';
import EnumSubTypeCaption from '@/logic/modeling/entity/EnumSubTypeCaption.js';
import ModelingApp from '@/logic/modeling/entity/ModelingApp.js';

import generateCode from './generate-code.vue';

export default {
    props: {
        app: {
            type: ModelingApp,
            required: true
        },
        clazz: {
            type: EnumClass,
            required: true
        },
        save: {
            type: Function,
            required: true,
        },
        active: {
            type: Boolean,
            required: true,
        },
    },
    data() {
        let subCaptions = [];
        for (let subCaption of this.clazz.subCaptions) {
            subCaptions.push(subCaption.clone());
        }
        let constants = [];
        for (let constant of this.clazz.constants) {
            constants.push(constant.clone());
        }
        return {
            model: {
                simple: this.clazz.simple,
                subCaptions: subCaptions,
                constants: constants,
            },
            constantRules: {
                name: [tnx.app.validator.requiredRule, tnx.app.validator.symbolRule],
                caption: [tnx.app.validator.manualInputRule],
                value: [tnx.app.validator.manualInputRule],
            },
            sceneRules: {
                subname: [tnx.app.validator.requiredRule, tnx.app.validator.symbolRule],
                caption: [tnx.app.validator.requiredRule, tnx.app.validator.manualInputRule],
            },
            saving: false,
            sceneEnabled: subCaptions.length > 0,
        };
    },
    computed: {
        sceneItems() {
            let items = [];
            for (let subCaption of this.model.subCaptions) {
                if (subCaption.subname && !items.contains(item => item.value === subCaption.subname)) {
                    items.push({
                        value: subCaption.subname,
                        text: subCaption.subname,
                    });
                }
            }
            return items;
        },
    },
    watch: {
        active() {
            if (this.active) {
                window.addEventListener('keydown', this.onKeydown);
            } else {
                window.removeEventListener('keydown', this.onKeydown);
            }
        },
    },
    created() {
        tnx.deepWatch(this, this.model, (newValue, oldValue, path) => {
            this.clazz.modified = true;
            console.info(this.clazz.getName() + ': ' + path + ': ' + tnx.util.string.toJson(
                oldValue) + ' -> ' + tnx.util.string.toJson(newValue));
        });
    },
    mounted() {
        window.addEventListener('keydown', this.onKeydown);
    },
    unmounted() {
        this.clazz.modified = false;
        window.removeEventListener('keydown', this.onKeydown);
    },
    methods: {
        newConstant() {
            let ordinal = this.model.constants.length + 1;
            let constant = new EnumConstant('CONSTANT' + ordinal);
            constant.caption = '常量' + ordinal;
            return constant;
        },
        cloneConstant(constant) {
            let newConstant = constant.clone();
            newConstant.ordinal = this.model.constants.length + 1;
            this.model.constants.push(newConstant);
        },
        newSubCaption() {
            let ordinal = this.model.subCaptions.length + 1;
            return new EnumSubTypeCaption('scene' + ordinal, '场景' + ordinal);
        },
        constantItems(scene) {
            let items = [];
            for (let constant of this.model.constants) {
                if (constant.scenes.includes(scene.subname)) {
                    items.push({
                        name: constant.name,
                        caption: constant.caption,
                    });
                }
            }
            return items;
        },
        toSave() {
            if (this.$refs.constantTable.validateTable()
                && (!this.$refs.sceneTable || this.$refs.sceneTable.validateTable())) {
                for (let constant1 of this.model.constants) {
                    for (let constant2 of this.model.constants) {
                        if (constant1 !== constant2 && constant1.name && constant1.name === constant2.name) {
                            tnx.error('常量定义名称重复：' + constant1.name);
                            return;
                        }
                        if (constant1 !== constant2 && constant1.caption && constant1.caption === constant2.caption) {
                            tnx.error('常量显示名称重复：' + constant1.caption);
                            return;
                        }
                        if (constant1 !== constant2 && constant1.value && constant1.value === constant2.value) {
                            tnx.error('常量持久化值重复：' + constant1.value);
                            return;
                        }
                    }
                }
                for (let subCaption1 of this.model.subCaptions) {
                    for (let subCaption2 of this.model.subCaptions) {
                        if (subCaption1 !== subCaption2 && subCaption1.subname === subCaption2.subname) {
                            tnx.error('场景定义名称重复：' + subCaption1.subname);
                            return;
                        }
                    }
                }
                tnx.showLoading();
                this.doSave(() => {
                    tnx.closeLoading();
                });
            } else {
                tnx.toast('字段校验未通过，请检查字段', undefined, {
                    type: 'error',
                });
            }
        },
        doSave(callback) {
            let model = Object.assign({}, this.model, {
                packageName: this.clazz.packageName,
                simpleName: this.clazz.simpleName,
            });
            this.saving = true;
            this.save(this.clazz.id, this.app, model, () => {
                setTimeout(() => {
                    this.clazz.modified = false;
                    this.saving = false;
                    if (typeof callback === 'function') {
                        callback();
                    }
                }, 300);
            });
        },
        onKeydown(event) {
            if (event.ctrlKey && event.key.toLowerCase() === 's') {
                this.toSave();
            }
        },
        toGenerateCode() {
            if (!this.clazz.modified) {
                tnx.open(generateCode, {
                    app: this.app,
                    clazz: this.clazz,
                });
            }
        },
    }
}
</script>

<style lang="scss" scoped>
.scene-constant-container {
    margin: 1px 2px;

    .el-tag {
        margin: 1px 2px 1px 0;
    }
}
</style>
